/* 
 * @(#)OverlayGroup.java
 *
 * Date: 6/11/2001
 *
 * Copyright 2001 Columbia University, All Rights Reserved.
 *
 * This software is the proprietary information of Columbia University.
 * Please contact Blaine Bell ([EMAIL PROTECTED]) for any bugs or possible enhancements.
 *
 */   

import javax.media.j3d.*;
import java.awt.*;
import javax.vecmath.*;
import java.util.*;

public class OverlayGroup {
	
	FixedCanvas3D _canvas=null;
	View _view=null;
	Group _group=null; 
	static Vector allOverlayGroups=new Vector(); 
	TransformGroup tg = new TransformGroup();
	boolean setup=false;
	boolean onNearClippingPlane=false, onNearSet=false;

	/** determines if you want to place the overlaygroup on the Near Clipping plane **/
	public void setOnNearClippingPlane(boolean b){
		onNearClippingPlane = b;
		if (b)
			onNearSet=false;
	}
	
	public OverlayGroup(){
		allOverlayGroups.add(this);
	}

	public void setupOverlayGroup(FixedCanvas3D c, Group groupAboveViewPlatform,Group overlayAnchor)  {
		_canvas = c;
		_view = _canvas.getView();
		_group = groupAboveViewPlatform;
		setup = true;
		if (!_group.isLive()){
			_group.setCapability(Group.ALLOW_CHILDREN_WRITE); 
			_group.setCapability(Group.ALLOW_CHILDREN_EXTEND); 
		}
		if (!tg.isLive()){
			tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
			tg.setCapability(Group.ALLOW_CHILDREN_WRITE);
		}
		tg.addChild(overlayAnchor);
		BranchGroup bg = new BranchGroup();
		bg.addChild(tg);
		_group.addChild(bg);
	}
	Dimension screenSize = new Dimension(),canvSize = new Dimension();
	/* from imageplane */
	double zdist=0.;

	static public void updateAllZValues(){
		for (Enumeration e=allOverlayGroups.elements();e.hasMoreElements();){
			((OverlayGroup)e.nextElement()).updatePlacement();
		}
	} 
	/** Allows the Z value to change.  
	 * @param z z-value in image-plate coordinates. Negative Z is typically further away
	 *          from the eyepoint
	 */
	public void updateZValue(double z){
		zdist = z;
		if (!onNearSet){
			if (setup){
				updatePlacement();
			}
		}
	}
	/** This function must be called once the View Model is set up properly 
	 *  in order for the overlaygroup to work. If any parameters of the View Model Changes,
	 * or the Z value is changed, this needs to be called again.
	 */
	public void updatePlacement(){
		_canvas.refreshAllVariables();
		if (onNearClippingPlane){
			/** This value is dependent on hardware/difference in clipping values
            between front and back clipping planes **/
			zdist = _canvas.computeFrontClipValueInImagePlate()-.0001;
			onNearSet=true;
		}
		Transform3D t=new Transform3D(),t2=new Transform3D(),t3=new Transform3D();
		Screen3D screen = _canvas.getScreen3D();
		Point3d eyepoint= new Point3d();
		screen.getSize(screenSize);
		_canvas.getSize(canvSize);
		_canvas.getCenterEyeInImagePlate(eyepoint);
		_canvas.getViewPlatformToImagePlate(t);
		Point3d screenOrigin = new Point3d();

		/* Translating eyepoint to origin */
		t2.set(new Vector3d(eyepoint));
		t.mul(t2);
		t3.setScale(( eyepoint.z-zdist)/eyepoint.z);
		t.mul(t3);

		t2.set(new Vector3d(-eyepoint.x,-eyepoint.y,-eyepoint.z));
		t.mul(t2);

		_canvas.getPixelLocationInImagePlate(0,canvSize.height-1,screenOrigin);
		t2.set(new Vector3d(screenOrigin));
		t.mul(t2);

		t3.setScale(new Vector3d(_canvas.getPhysicalWidth()/canvSize.width,
				_canvas.getPhysicalHeight()/canvSize.height,
				_canvas.getPhysicalWidth()/canvSize.width));
		t.mul(t3);
		tg.setTransform(t);
	}
}
